home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / game / shoot / ADoom_src_1_2.lha / ADoom_src / amiga_video.c < prev    next >
C/C++ Source or Header  |  1998-03-08  |  57KB  |  1,732 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <exec/exec.h>
  6. #include <dos/dos.h>
  7. #include <graphics/gfx.h>
  8. #include <graphics/gfxbase.h>
  9. #include <graphics/gfxmacros.h>
  10. #include <intuition/intuition.h>
  11. #include <libraries/asl.h>
  12. #include <libraries/lowlevel.h>
  13. #include <cybergraphics/cybergraphics.h>
  14. #include <devices/gameport.h>
  15. #include <devices/timer.h>
  16. #include <devices/keymap.h>
  17.  
  18. #include <proto/exec.h>
  19. #include <proto/dos.h>
  20. #include <proto/graphics.h>
  21. #include <proto/layers.h>
  22. #include <proto/intuition.h>
  23. #include <proto/asl.h>
  24. #include <proto/timer.h>
  25. #include <proto/keymap.h>
  26. #include <proto/lowlevel.h>
  27. #include <proto/cybergraphics.h>
  28.  
  29. #ifdef GRAFFITI
  30. #include "graffiti.h"
  31. #include "graffiti_lib.h"
  32. #include "graffiti_protos.h"
  33. #endif
  34.  
  35. #include "doomtype.h"
  36. #include "doomdef.h"
  37. #include "doomstat.h"
  38. #include "i_system.h"
  39. #include "i_video.h"
  40. #include "v_video.h"
  41. #include "m_argv.h"
  42. #include "m_bbox.h"
  43. #include "d_main.h"
  44.  
  45. #include "amiga_median.h"
  46. #include "c2p_020.h"
  47. #include "c2p_030.h"
  48. #include "c2p_040.h"
  49. #include "c2p8_040_amlaukka.h"
  50. #include "amiga_mmu.h"
  51. #include "amiga_sega.h"
  52. #include "r_draw.h"
  53. #include "w_wad.h"
  54. #include "z_zone.h"
  55.  
  56. /*experimental_c2p_stuff***********************************************/
  57. extern int scaledviewwidth;
  58. void REGARGS (*c2p)(REG(a0, const UBYTE *chunky),
  59.                     REG(a1, UBYTE *raster),
  60.                     REG(a2, const UBYTE *chunky_end)) = NULL;
  61.  
  62. /**********************************************************************/
  63. extern struct ExecBase *SysBase;
  64. struct Library *AslBase = NULL;
  65. struct Library *CyberGfxBase = NULL;
  66. struct Library *LowLevelBase = NULL;
  67. struct Library *KeymapBase = NULL;
  68.  
  69. extern int cpu_type;
  70.  
  71. int SCREENWIDTH;
  72. int SCREENHEIGHT;
  73. int weirdaspect;
  74.  
  75. #define NUMPALETTES 14
  76.  
  77. static struct ScreenModeRequester *video_smr = NULL;
  78. static struct Screen *video_screen = NULL;
  79. static struct Window *video_window = NULL;
  80. static struct BitMap video_bitmap[3] = {
  81.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  82.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  83.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}
  84. };
  85. static PLANEPTR video_raster[3] = {NULL, NULL, NULL};    /* contiguous bitplanes */
  86. static UBYTE *video_compare_buffer[3] = {NULL, NULL, NULL};    /* in fastmem */
  87. static struct RastPort video_rastport[3];
  88. static struct ScreenBuffer *video_sb[2] = {NULL, NULL};
  89. static struct DBufInfo *video_db = NULL;
  90. static struct MsgPort *video_mp = NULL;
  91. static int video_which = 0;
  92. static BYTE video_sigbit1 = -1;
  93. static BYTE video_sigbit2 = -1;
  94. static volatile BYTE video_sigbit3 = -1;
  95. static UBYTE *video_chipbuff = NULL;
  96. static struct Task *video_maintask;
  97. static struct Task *video_fliptask = NULL;
  98. static int video_depth = 0;
  99. static int video_oscan_height;
  100. static FAR ULONG video_colourtable[NUMPALETTES][1 + 3*256 + 1];
  101. static int video_palette_index = 0;
  102. static int video_pending_palette_index = 0;
  103. static volatile WORD video_palette_changed = 0;
  104. static UBYTE video_xlate[NUMPALETTES][256]; /* xlate 8-bit to 6-bit EHB */
  105. static BOOL video_is_ehb_mode = FALSE;
  106. static BOOL video_is_native_mode = FALSE;
  107. static BOOL video_is_cyber_mode = FALSE;
  108. static BOOL video_is_using_blitter = FALSE;
  109. static BOOL video_blit_is_in_progress = FALSE;
  110. static BOOL video_use_mmu = FALSE;
  111. static BOOL video_is_directcgx = FALSE;
  112. static BOOL video_doing_fps = FALSE;
  113. static BOOL video_bitmap_is_locked = FALSE;
  114. static APTR video_bitmap_handle;
  115. static int video_f_cache_mode;
  116. static int video_c_cache_mode;
  117. static struct RastPort video_temprp;
  118. static struct BitMap video_tmp_bm = {
  119.   0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
  120. };
  121. static UWORD __chip emptypointer[] = {
  122.   0x0000, 0x0000,    /* reserved, must be NULL */
  123.   0x0000, 0x0000,     /* 1 row of image data */
  124.   0x0000, 0x0000    /* reserved, must be NULL */
  125. };
  126.  
  127. /* keyboard */
  128. static BOOL video_is_rawkey;
  129.  
  130. /* gameport stuff */
  131. static struct MsgPort *gameport_mp = NULL;
  132. static struct IOStdReq *gameport_io = NULL;
  133. static BOOL gameport_is_open = FALSE;
  134. static BOOL gameport_io_in_progress = FALSE;
  135. static struct InputEvent gameport_ie;
  136. static BYTE gameport_ct;        /* controller type */
  137. struct GamePortTrigger gameport_gpt = {
  138.   GPTF_UPKEYS | GPTF_DOWNKEYS,    /* gpt_Keys */
  139.   0,                /* gpt_Timeout */
  140.   1,                /* gpt_XDelta */
  141.   1                /* gpt_YDelta */
  142. };
  143.  
  144. /* SEGA variables */
  145. static ULONG prevSega;
  146. static BOOL sega3_selected = FALSE;
  147. static BOOL sega6_selected = FALSE;
  148.  
  149. #ifdef GRAFFITI
  150. struct Library *GraffitiBase = NULL;
  151. int video_graffiti = 0;
  152. static struct GRF_Screen *video_grf_screen = NULL;
  153. #endif
  154.  
  155. /****************************************************************************/
  156. struct Library *TimerBase = NULL;
  157. static struct MsgPort *timermp = NULL;
  158. static struct timerequest *timerio = NULL;
  159. static ULONG timerclosed = TRUE;
  160. static ULONG eclocks_per_second; /* EClock frequency in Hz */
  161.  
  162. static struct EClockVal start_time;
  163. static unsigned int blit_time = 0;
  164. static unsigned int safe_time = 0;
  165. static unsigned int c2p_time = 0;
  166. static unsigned int ccs_time = 0;
  167. static unsigned int wpa8_time = 0;
  168. static unsigned int lock_time = 0;
  169. static unsigned int total_frames = 0;
  170.  
  171. /****************************************************************************/
  172. static __inline void start_timer (void)
  173. {
  174.   ReadEClock (&start_time);
  175. }
  176.  
  177. /****************************************************************************/
  178. static __inline unsigned int end_timer (void)
  179. {
  180.   struct EClockVal end_time;
  181.  
  182.   ReadEClock (&end_time);
  183.   return end_time.ev_lo - start_time.ev_lo;
  184. }
  185.  
  186. /****************************************************************************/
  187.  
  188. static char *mode_name (ULONG mode)
  189. /* Return a mode name for given mode, compatible with ASL mode requester */
  190. /* Use name in DisplayInfo database if available */
  191. /* else manually construct the name */
  192. {
  193.   APTR handle;
  194.   char *p;
  195.   struct NameInfo nameinfo;
  196.   struct DimensionInfo dimsinfo;
  197.   static char modename[DISPLAYNAMELEN + 4 + 4 + 11 + 1];
  198.  
  199.   p = modename;
  200.   *p = '\0';
  201.   if ((handle = FindDisplayInfo (mode & ~SPRITES)) != NULL) {
  202.     if (GetDisplayInfoData (handle, (UBYTE *)&nameinfo,
  203.                             sizeof(nameinfo), DTAG_NAME,
  204.                             NULL) > sizeof(struct QueryHeader)) {
  205.       p += sprintf (p, "%s", nameinfo.Name);
  206.     } else if (GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  207.                                    sizeof(dimsinfo), DTAG_DIMS,
  208.                                    NULL) >= 66 /* sizeof(dimsinfo)*/) {
  209.       switch (mode & MONITOR_ID_MASK) {
  210.         case DEFAULT_MONITOR_ID:
  211.           p += sprintf (p, "DEFAULT:");      /* PAL or NTSC??? */
  212.           break;
  213.         case NTSC_MONITOR_ID:
  214.           p += sprintf (p, "NTSC:");
  215.           break;
  216.         case PAL_MONITOR_ID:
  217.           p += sprintf (p, "PAL:");
  218.           break;
  219.         case VGA_MONITOR_ID:
  220.           p += sprintf (p, "MULTISCAN:");
  221.           break;
  222.         case A2024_MONITOR_ID:
  223.           p += sprintf (p, "A2024:");
  224.           break;
  225.         case PROTO_MONITOR_ID:
  226.           p += sprintf (p, "PROTO:");
  227.           break;
  228.         case EURO72_MONITOR_ID:
  229.           p += sprintf (p, "EURO72:");
  230.           break;
  231.         case EURO36_MONITOR_ID:
  232.           p += sprintf (p, "EURO36:");
  233.           break;
  234.         case SUPER72_MONITOR_ID:
  235.           p += sprintf (p, "SUPER72:");
  236.           break;
  237.         case DBLNTSC_MONITOR_ID:
  238.           p += sprintf (p, "DBLNTSC:");
  239.           break;
  240.         case DBLPAL_MONITOR_ID:
  241.           p += sprintf (p, "DBLPAL:");
  242.           break;
  243.         default:
  244.           p += sprintf (p, "(unknown):");
  245.           break;
  246.       }
  247.       p += sprintf (p, "%d x %d",
  248.                     dimsinfo.Nominal.MaxX - dimsinfo.Nominal.MinX + 1,
  249.                     dimsinfo.Nominal.MaxY - dimsinfo.Nominal.MinY + 1);
  250.       if ((mode & HAM_KEY) != 0)
  251.         p += sprintf (p, " HAM");
  252.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  253.         p += sprintf (p, " EHB");
  254.       if ((mode & LACE) != 0)
  255.         p += sprintf (p, " Interlaced");
  256.     } else {
  257.       p += sprintf (p, "%s", "(unnamed)");
  258.       if ((mode & HAM_KEY) != 0)
  259.         p += sprintf (p, " HAM");
  260.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  261.         p += sprintf (p, " EHB");
  262.       if ((mode & LACE) != 0)
  263.         p += sprintf (p, " Interlaced");
  264.     }
  265.   } else {
  266.     p += sprintf (p, "%s", "(unavailable)");
  267.   }
  268.   return (modename);
  269. }
  270.  
  271. /****************************************************************************/
  272.  
  273. static ULONG parse_mode (char *modename)
  274. /* Modename may be descriptive name ("PAL Lores"), or hex ("$00420001" or */
  275. /* "0x12345678") or decimal ("32768"). */
  276. {
  277.   ULONG mode, reason;
  278.  
  279.   mode = INVALID_ID;
  280.   if (modename != NULL) {
  281.     if (modename[0] == '0' && modename[1] == 'x') {
  282.       if (sscanf (&modename[2], "%lx", &mode) != 1)
  283.         mode = INVALID_ID;
  284.     } else if (modename[0] == '$') {
  285.       if (sscanf (&modename[1], "%lx", &mode) != 1)
  286.         mode = INVALID_ID;
  287.     } else if (modename[0] >= '0' && modename[0] <= '9') {
  288.       if (sscanf (modename, "%ld", &mode) != 1)
  289.         mode = INVALID_ID;
  290.     } else {
  291.       while ((mode = NextDisplayInfo (mode)) != INVALID_ID) {
  292.         if ((mode & LORESDPF_KEY) == 0) {
  293.           /* printf ("$%08x  \"%s\"\n", mode, mode_name (mode)); */
  294.           if (strcmp (mode_name (mode), modename) == 0)
  295.             break;
  296.         }
  297.       }
  298.     }
  299.   }
  300.   if (FindDisplayInfo (mode) == NULL)
  301.     I_Error ("ScreenMode not in database: \"%s\"", modename);
  302.   if ((reason = ModeNotAvailable (mode)) != 0)
  303.     I_Error ("Mode $%08x is not available: %ld", mode, reason);
  304.   return (mode);
  305. }
  306.  
  307. /**********************************************************************/
  308. static void video_do_fps (struct RastPort *rp, int yoffset)
  309. {
  310.   ULONG x;
  311.   static struct EClockVal start_time = {0, 0};
  312.   struct EClockVal end_time;
  313.   char msg[4];
  314.  
  315.   ReadEClock (&end_time);
  316.   x = end_time.ev_lo - start_time.ev_lo;
  317.   if (x != 0) {
  318.     x = (eclocks_per_second + (x >> 1)) / x;   /* round to nearest */
  319.     msg[0] = (x % 1000) / 100 + '0';
  320.     msg[1] = (x % 100) / 10 + '0';
  321.     msg[2] = (x % 10) + '0';
  322.     msg[3] = '\0';
  323.     Move (rp, SCREENWIDTH - 24, yoffset + 6);
  324.     Text (rp, msg, 3);
  325.   }
  326.   start_time = end_time;
  327. }
  328.  
  329. /**********************************************************************/
  330. // This asynchronous task waits in a loop for sigbit3 signals.
  331. // Sigbit3 is signalled when the next frame is just finished.
  332. // Sigbit3 may be signalled from the qblit() cleanup function or from the
  333. // main task.
  334. // On sigbit3, we load the new palette and call ChangeScreenBuffer().
  335. // This way there is no delay calling ChangeScreenBuffer() after the last blit
  336. // has finished.
  337. // The main 3D rendering task may be interrupted to call ChangeScreenBuffer()
  338. // SIGBREAKF_CTRL_F and SIGBREAKF_CTRL_C are used for synchronisation
  339. // with the main task.
  340.  
  341. static void __saveds __interrupt video_flipscreentask (void)
  342. {
  343.   ULONG sig;
  344.   struct MsgPort *video_dispport, *video_safeport;
  345.   BOOL going, video_disp, video_safe;
  346.   int i;
  347.  
  348.   video_sigbit3 = AllocSignal(-1);
  349.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  350.   video_dispport = CreatePort (NULL, 0);
  351.   video_safeport = CreatePort (NULL, 0);
  352.   video_disp = TRUE;
  353.   video_safe = TRUE;
  354.   for (i = 0; i < 2; i++) {
  355.     video_sb[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = video_dispport;
  356.     video_sb[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = video_safeport;
  357.   }
  358.   going = (video_sigbit3 != -1) &&
  359.           (video_dispport != NULL) &&
  360.           (video_safeport != NULL);
  361.   while (going) {
  362.     sig = Wait (1 << video_sigbit3 | SIGBREAKF_CTRL_C);
  363.     if ((sig & (1 << video_sigbit3)) != 0) {
  364.       if (video_doing_fps)
  365.         video_do_fps (&video_rastport[video_which], 0);
  366.       if (video_palette_changed > 0) {
  367.         LoadRGB32 (&video_screen->ViewPort,
  368.                    video_colourtable[video_palette_index]);
  369.         video_palette_changed--; /* keep it set for 2 frames for dblbuffing */
  370.       }
  371.       if ((ChangeScreenBuffer (video_screen, video_sb[video_which])) != 0) {
  372.         video_disp = FALSE;
  373.         video_safe = FALSE;
  374.       }
  375.       if (!video_safe) {  /* wait until safe */
  376.         Wait (1 << video_safeport->mp_SigBit);
  377.         while (GetMsg (video_safeport) != NULL) /* clear message queue */
  378.           /* do nothing */ ;
  379.         video_safe = TRUE;
  380.       }
  381.       Signal (video_maintask, SIGBREAKF_CTRL_F);
  382.       if (!video_disp) {  /* wait for previous frame to be displayed */
  383.         Wait (1 << video_dispport->mp_SigBit);
  384.         while (GetMsg (video_dispport) != NULL) /* clear message queue */
  385.           /* do nothing */ ;
  386.         video_disp = TRUE;
  387.       }
  388.     }
  389.     if ((sig & SIGBREAKF_CTRL_C) != 0) {
  390.       going = FALSE;
  391.     }
  392.   }
  393.   if (!video_safe) {  /* wait for safe */
  394.     Wait (1 << video_safeport->mp_SigBit);
  395.     while (GetMsg (video_safeport) != NULL) /* clear message queue */
  396.       /* do nothing */ ;
  397.     video_safe = TRUE;
  398.   }
  399.   if (!video_disp) {  /* wait for last frame to be displayed */
  400.     Wait (1 << video_dispport->mp_SigBit);
  401.     while (GetMsg (video_dispport) != NULL) /* clear message queue */
  402.       /* do nothing */ ;
  403.     video_disp = TRUE;
  404.   }
  405.   if (video_sigbit3 != -1)
  406.     FreeSignal (video_sigbit3);
  407.   if (video_dispport != NULL)
  408.     DeletePort (video_dispport);
  409.   if (video_safeport != NULL)
  410.     DeletePort (video_safeport);
  411.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  412.   Wait (0);
  413. }
  414.  
  415. /**********************************************************************/
  416. // Called by D_DoomMain,
  417. // determines the hardware configuration
  418. // and sets up the video mode
  419. void I_InitGraphics (void)
  420. {
  421.   int i;
  422.   ULONG propertymask, idcmp, wflags, width, pixfmt;
  423.   struct Rectangle rect;
  424.   char reqtitle[32];
  425.   int mode, depth, nbytes, p;
  426.   DisplayInfoHandle handle;
  427.   struct DisplayInfo dispinfo;
  428.   struct DimensionInfo dimsinfo;
  429.   static struct TextAttr topaz8 = {
  430.     "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
  431.   };
  432.  
  433.   video_maintask = FindTask(NULL);
  434.  
  435.   if ((KeymapBase = OpenLibrary ("keymap.library", 0)) == NULL)
  436.     I_Error ("Can't open keymap.library");
  437.  
  438.   if ((timermp = CreatePort (NULL, 0)) == NULL)
  439.     I_Error ("Can't create messageport!");
  440.   if ((timerio = (struct timerequest *)CreateExtIO (timermp,
  441.                   sizeof(struct timerequest))) == NULL)
  442.     I_Error ("Can't create External IO!");
  443.   if (timerclosed = OpenDevice (TIMERNAME, UNIT_ECLOCK,
  444.                                 (struct IORequest *)timerio, 0))
  445.     I_Error ("Can't open timer.device!");
  446.   TimerBase = (struct Library *)timerio->tr_node.io_Device;
  447.   eclocks_per_second = ReadEClock (&start_time);
  448.  
  449.   video_doing_fps = M_CheckParm ("-fps");
  450.  
  451. #ifdef GRAFFITI
  452.   if (video_graffiti != 0) {
  453.     if ((GraffitiBase = OpenLibrary ("graffiti.library", 0)) == NULL)
  454.       I_Error ("Can't open graffiti.library");
  455.     if ((video_grf_screen = OpenChunkyScreen (video_graffiti)) == NULL)
  456.       I_Error ("graffiti.library OpenChunkyScreen() failed");
  457.     video_screen = (struct Screen *)video_grf_screen->GRF_ScreenID;
  458.     video_depth = 8;
  459.   } else {
  460. #endif
  461.  
  462.     if (AslBase == NULL) {
  463.       if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
  464.           (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
  465.         I_Error ("OpenLibrary(""asl.library"", 37) failed");
  466.       }
  467.     }
  468.  
  469.     CyberGfxBase = OpenLibrary ("cybergraphics.library", 0); /* may be NULL */
  470.  
  471.     /* first check tooltypes for SCREENMODE */
  472.     mode = -1;
  473.     p = M_CheckParm ("-screenmode");
  474.     if (p && p < myargc - 1) {
  475.       mode = parse_mode (myargv[p+1]);
  476.     }
  477.  
  478.     /* if not found in icon tooltypes, then put up a ScreenMode requester */
  479.     if (mode == -1) {
  480.       propertymask = /* DIPF_IS_EXTRAHALFBRITE | */ DIPF_IS_DUALPF |
  481.                      DIPF_IS_PF2PRI | DIPF_IS_HAM;
  482.       if (CyberGfxBase != NULL)
  483.         mode = BestCModeIDTags (CYBRBIDTG_NominalWidth, SCREENWIDTH,
  484.                                 CYBRBIDTG_NominalHeight, SCREENHEIGHT,
  485.                                 CYBRBIDTG_Depth,    8,
  486.                                 TAG_DONE);
  487.       else if (GfxBase->LibNode.lib_Version >= 39)
  488.         mode = BestModeID (BIDTAG_NominalWidth,     SCREENWIDTH,
  489.                            BIDTAG_NominalHeight,    SCREENHEIGHT,
  490.                            BIDTAG_Depth,            video_depth,
  491.                            BIDTAG_DIPFMustNotHave,  propertymask,
  492.                            TAG_DONE);
  493.       else
  494.         mode = EXTRAHALFBRITE_KEY;
  495.       if (AslBase->lib_Version >= 38) {
  496.         sprintf (reqtitle, "ADoom %dx%d", SCREENWIDTH, SCREENHEIGHT);
  497.         if (!AslRequestTags (video_smr,
  498.                              ASLSM_TitleText,        (ULONG)reqtitle,
  499.                              ASLSM_InitialDisplayID, mode,
  500.                              ASLSM_MinWidth,         SCREENWIDTH,
  501.                              ASLSM_MinHeight,        SCREENHEIGHT,
  502.                              ASLSM_MaxWidth,         MAXSCREENWIDTH,
  503.                              ASLSM_MaxHeight,        MAXSCREENHEIGHT,
  504.                              ASLSM_MinDepth,         6,
  505.                              ASLSM_MaxDepth,         8,
  506.                              ASLSM_PropertyMask,     propertymask,
  507.                              ASLSM_PropertyFlags,    0,
  508.                              TAG_DONE)) {
  509.           I_Error ("AslRequest() failed");
  510.         }
  511.         mode = video_smr->sm_DisplayID;
  512.       }
  513.     }
  514.  
  515.     if ((handle = FindDisplayInfo (mode)) == NULL) {
  516.       I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
  517.     }
  518.     if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
  519.                                       sizeof(struct DisplayInfo), DTAG_DISP,
  520.                                       NULL)) < 40 /*sizeof(struct DisplayInfo)*/) {
  521.       I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  522.                mode, nbytes);
  523.     }
  524.     if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  525.                                       sizeof(dimsinfo), DTAG_DIMS,
  526.                                       NULL)) < 66 /* sizeof(dimsinfo)*/) {
  527.       I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  528.                mode, nbytes);
  529.     }
  530.  
  531.     video_oscan_height = dimsinfo.MaxOScan.MaxY - dimsinfo.MaxOScan.MinY + 1;
  532.  
  533.     video_is_cyber_mode = 0;
  534.     if (CyberGfxBase != NULL)
  535.       video_is_cyber_mode = IsCyberModeID (mode);
  536.  
  537.     /* this test needs improving */
  538.     video_is_native_mode = ((GfxBase->LibNode.lib_Version < 39 ||
  539.                              (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
  540.                              (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
  541.                              (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
  542.                              (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
  543.                             !video_is_cyber_mode &&
  544.                             (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
  545.  
  546.     video_is_ehb_mode = ((dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0);
  547.  
  548.     /* manual overrides */
  549.     if (M_CheckParm ("-rtg"))
  550.       video_is_native_mode = FALSE;
  551.     else if (M_CheckParm ("-native"))
  552.       video_is_native_mode = TRUE;
  553.     if (M_CheckParm ("-ehb"))
  554.       video_is_ehb_mode = TRUE;
  555.  
  556.     printf ("Screen Mode $%08x is ", mode);
  557.     if (video_is_native_mode)
  558.       printf (" NATIVE-PLANAR");
  559.     else
  560.       printf (" FOREIGN");
  561.     if (video_is_ehb_mode)
  562.       printf (" EXTRAHALFBRITE");
  563.     else
  564.       printf (" 8-BIT");
  565.     if (video_is_cyber_mode)
  566.       printf (" CYBERGRAPHX");
  567.     printf ("\n");
  568.   
  569.     if (video_is_ehb_mode)
  570.       video_depth = 6;
  571.     else
  572.       video_depth = 8;
  573.  
  574.     rect.MinX = 0;
  575.     rect.MinY = 0;
  576.     rect.MaxX = SCREENWIDTH - 1;
  577.     rect.MaxY = SCREENHEIGHT - 1;
  578.  
  579.     if (M_CheckParm ("-mmu") && cpu_type >= 68040)
  580.       video_use_mmu = true;
  581.  
  582.     if (video_is_native_mode) {
  583.       video_is_using_blitter = (cpu_type < 68040);
  584.  
  585.       for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  586.         /* use the mmu hack only if cpu is 68040+ and user specified -mmu */
  587.         if (video_use_mmu) {
  588.           ULONG *ptr, mem;
  589.           mem = (ULONG)AllocVec (SCREENWIDTH * SCREENHEIGHT / 8 * video_depth +
  590.                                  4100, MEMF_CHIP);
  591.           if (!mem)
  592.             I_Error ("AllocVec() failed");
  593.           ptr = (ULONG*)((mem & ~0xfff) + 4096);
  594.       ptr[-1] = 4096 - (mem & 0xfff);
  595.       video_raster[i] = (byte *)ptr;
  596.           video_c_cache_mode = mmu_mark (video_raster[i],
  597.                                      SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  598.                                      CM_IMPRECISE, SysBase);
  599.         } else {
  600.           if ((video_raster[i] = (PLANEPTR)AllocRaster (SCREENWIDTH,
  601.                                              video_depth * SCREENHEIGHT)) == NULL)
  602.             I_Error ("AllocRaster() failed");
  603.         }
  604.         memset (video_raster[i], 0, video_depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT));
  605.         InitBitMap (&video_bitmap[i], video_depth, SCREENWIDTH, SCREENHEIGHT);
  606.         for (depth = 0; depth < video_depth; depth++)
  607.           video_bitmap[i].Planes[depth] = video_raster[i] +
  608.                                       depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT);
  609.         InitRastPort (&video_rastport[i]);
  610.         video_rastport[i].BitMap = &video_bitmap[i];
  611.         SetAPen (&video_rastport[i], (1 << video_depth) - 1);
  612.         SetBPen (&video_rastport[i], 0);
  613.         SetDrMd (&video_rastport[i], JAM2);
  614.       }
  615.  
  616.       /* experimental c2p stuff */
  617.       if (!video_is_using_blitter)
  618.         c2p = c2p8_reloc (screens[0], &video_bitmap[0], SysBase);
  619.  
  620.       if ((video_screen = OpenScreenTags (NULL,
  621.             SA_Type,        CUSTOMSCREEN | CUSTOMBITMAP,
  622.             SA_DisplayID,   mode,
  623.             SA_DClip,       (ULONG)&rect,
  624.             SA_Width,       SCREENWIDTH,
  625.             SA_Height,      SCREENHEIGHT,
  626.             SA_Depth,       video_depth,
  627.             SA_Font,        &topaz8,
  628.             /* SA_Draggable,FALSE, */
  629.             /* SA_AutoScroll,FALSE, */
  630.             /* SA_Exclusive,TRUE, */
  631.             SA_Quiet,       TRUE,
  632.             SA_BitMap,      &video_bitmap[0], /* custom bitmap, contiguous planes */
  633.             TAG_DONE,       0)) == NULL) {
  634.         I_Error ("OpenScreen() failed");
  635.       }
  636.       for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  637.         if ((video_compare_buffer[i] = malloc (SCREENWIDTH * SCREENHEIGHT)) == NULL)
  638.           I_Error ("Out of memory allocating %d bytes", SCREENWIDTH * SCREENHEIGHT);
  639.         memset (video_compare_buffer[i], 0, SCREENWIDTH * SCREENHEIGHT);
  640.       }
  641.       if (video_is_using_blitter) {
  642.         for (i = 0; i < 2; i++) {
  643.       if ((video_sb[i] = AllocScreenBuffer (video_screen, &video_bitmap[i], 0)) == NULL)
  644.         I_Error ("Can't allocate structure for double buffering");
  645.         }
  646.       } else {
  647.         video_db = AllocDBufInfo (&video_screen->ViewPort);
  648.         video_mp = CreateMsgPort ();
  649.         if (!video_db || !video_mp)
  650.           I_Error ("Can't allocate dbuffer information");
  651.         video_db->dbi_DispMessage.mn_ReplyPort = video_mp;
  652.         video_which = 1;
  653.         ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[0], video_db);
  654.       }
  655.     } else {  /* non-native ScreenMode */
  656.       if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
  657.         video_is_directcgx = TRUE;
  658.       if ((video_screen = OpenScreenTags (NULL,
  659.             SA_Type,        CUSTOMSCREEN,
  660.             SA_DisplayID,   mode,
  661.             SA_DClip,       (ULONG)&rect,
  662.             SA_Width,       SCREENWIDTH,
  663.             SA_Height,      video_is_directcgx ? video_oscan_height << 1
  664.                                                : SCREENHEIGHT,
  665.             SA_Depth,       video_depth,
  666.             SA_Font,        &topaz8,
  667.             /* SA_Draggable,FALSE, */
  668.             /* SA_AutoScroll,FALSE, */
  669.             /* SA_Exclusive,TRUE, */
  670.             SA_Quiet,       TRUE,
  671.             TAG_DONE,       0)) == NULL) {
  672.         I_Error ("OpenScreen() failed");
  673.       }
  674.     }
  675.  
  676.     if (video_is_directcgx) {
  677.       video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  678.                                             LBMI_WIDTH,       &width,
  679.                                             LBMI_DEPTH,       &depth,
  680.                                             LBMI_PIXFMT,      &pixfmt,
  681.                                             LBMI_BASEADDRESS, &screens[0],
  682.                                             TAG_DONE);
  683.       UnLockBitMap (video_bitmap_handle);
  684.       if (/* width != SCREENWIDTH || */
  685.           depth != video_depth ||
  686.           pixfmt != PIXFMT_LUT8) {
  687.         I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
  688.                  width, depth, pixfmt);
  689.       }
  690.     } else {
  691.       if (video_use_mmu) {
  692.         video_f_cache_mode = mmu_mark (screens[0],
  693.                                        (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  694.                                        CM_WRITETHROUGH, SysBase);
  695.       }
  696.     }
  697.  
  698. #ifdef GRAFFITI
  699.   }
  700. #endif
  701.  
  702.   idcmp = IDCMP_RAWKEY;
  703.   wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP | WFLG_NOCAREREFRESH |
  704.            WFLG_SIMPLE_REFRESH;
  705.   if (M_CheckParm("-mouse") != NULL) {
  706.     idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
  707.     wflags |= WFLG_REPORTMOUSE;
  708.   }
  709.  
  710.   if ((video_window = OpenWindowTags (NULL,
  711.         WA_Left,         0,
  712.         WA_Top,          0,
  713.         WA_Width,        video_graffiti != 0 ? 640 : SCREENWIDTH,
  714.         WA_Height,       video_is_directcgx ? video_oscan_height << 1
  715.                                             : SCREENHEIGHT,
  716.         WA_IDCMP,        idcmp,
  717.         WA_Flags,        wflags,
  718.         WA_CustomScreen, video_screen,
  719.         TAG_DONE)) == NULL) {
  720.     I_Error ("OpenWindow() failed");
  721.   }
  722.  
  723.   InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
  724.   for (depth = 0; depth < video_depth; depth++)
  725.     if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
  726.       I_Error ("AllocRaster() failed");
  727.   video_temprp = *video_window->RPort;
  728.   video_temprp.Layer = NULL;
  729.   video_temprp.BitMap = &video_tmp_bm;
  730.  
  731.   if (video_is_native_mode) {
  732.     if (video_is_using_blitter) {
  733.       if ((video_sigbit1 = AllocSignal(-1)) == -1 ||
  734.       (video_sigbit2 = AllocSignal(-1)) == -1)
  735.     I_Error ("Can't allocate signal!\n");
  736.       Signal (video_maintask, (1 << video_sigbit1) | (1 << video_sigbit2));
  737.                                                 /* initial state is finished */
  738.       if ((video_fliptask = CreateTask ("ADoom_flipscreen", 100,
  739.                     video_flipscreentask, 4096)) == NULL)
  740.         I_Error ("Can't create subtask");
  741.       Wait (SIGBREAKF_CTRL_F);
  742.       if (video_sigbit3 == -1)
  743.     I_Error ("Subtask couldn't allocate sigbit");
  744.       if ((video_chipbuff = AllocMem (2 * SCREENWIDTH * SCREENHEIGHT,
  745.                                       MEMF_CHIP | MEMF_CLEAR)) == NULL)
  746.         I_Error ("Out of CHIP memory allocating %d bytes",
  747.                  2 * SCREENWIDTH * SCREENHEIGHT);
  748.       if (!video_is_ehb_mode)
  749.         c2p1x1_cpu3blit1_queue_init (SCREENWIDTH, SCREENHEIGHT, 0,
  750.                                      SCREENWIDTH * SCREENHEIGHT / 8,
  751.                                      1 << video_sigbit1, 1 << video_sigbit3,
  752.                                      video_maintask, video_fliptask,
  753.                                      video_chipbuff);
  754.     }
  755.   }
  756.  
  757.   if (!M_CheckParm ("-mousepointer"))
  758.     SetPointer (video_window, emptypointer, 1, 16, 0, 0);
  759.  
  760.   I_RecalcPalettes ();
  761.  
  762.   /* keyboard & joystick initialisation */
  763.  
  764.   video_is_rawkey = M_CheckParm ("-rawkey");
  765.  
  766.   if (M_CheckParm ("-sega3") != NULL)
  767.     sega3_selected = TRUE;
  768.  
  769.   if (M_CheckParm ("-sega6") != NULL)
  770.     sega6_selected = TRUE;
  771.  
  772.   if (M_CheckParm ("-joypad") != NULL) {
  773.  
  774.     if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
  775.       I_Error ("-joypad option specified and can't open lowlevel.library");
  776.  
  777.   } else {
  778.  
  779.     if ((gameport_mp = CreatePort (NULL, 0)) == NULL ||
  780.         (gameport_io = (struct IOStdReq *)CreateExtIO (gameport_mp,
  781.                                               sizeof(struct IOStdReq))) == NULL ||
  782.         OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
  783.       I_Error ("Can't open gameport.device");
  784.  
  785.     gameport_is_open = TRUE;
  786.  
  787.     Forbid ();
  788.  
  789.     gameport_io->io_Command = GPD_ASKCTYPE;
  790.     gameport_io->io_Length = 1;
  791.     gameport_io->io_Data = &gameport_ct;
  792.     DoIO ((struct IORequest *)gameport_io);
  793.  
  794.     if (gameport_ct != GPCT_NOCONTROLLER) {
  795.  
  796.       Permit ();
  797.       fprintf (stderr, "Another task is using the gameport!  Joystick disabled");
  798.       CloseDevice ((struct IORequest *)gameport_io);
  799.       gameport_is_open = FALSE;
  800.  
  801.     } else {
  802.  
  803.       gameport_ct = GPCT_ABSJOYSTICK;
  804.       gameport_io->io_Command = GPD_SETCTYPE;
  805.       gameport_io->io_Length = 1;
  806.       gameport_io->io_Data = &gameport_ct;
  807.       DoIO ((struct IORequest *)gameport_io);
  808.  
  809.       Permit ();
  810.  
  811.       gameport_io->io_Command = GPD_SETTRIGGER;
  812.       gameport_io->io_Length = sizeof(struct GamePortTrigger);
  813.       gameport_io->io_Data = &gameport_gpt;
  814.       DoIO ((struct IORequest *)gameport_io);
  815.  
  816.       gameport_io->io_Command = GPD_READEVENT;
  817.       gameport_io->io_Length = sizeof (struct InputEvent);
  818.       gameport_io->io_Data = &gameport_ie;
  819.       SendIO ((struct IORequest *)gameport_io);
  820.       gameport_io_in_progress = TRUE;
  821.     }
  822.   }
  823. }
  824.  
  825. /**********************************************************************/
  826. void I_ShutdownGraphics (void)
  827. {
  828.   int depth, i;
  829.  
  830.   if (video_is_directcgx && video_bitmap_is_locked) {
  831.     UnLockBitMap (video_bitmap_handle);
  832.     video_bitmap_is_locked = FALSE;
  833.   }
  834.   if (LowLevelBase != NULL) {
  835.     CloseLibrary (LowLevelBase);
  836.     LowLevelBase = NULL;
  837.   }
  838.   if (gameport_io_in_progress) {
  839.     AbortIO ((struct IORequest *)gameport_io);
  840.     WaitIO ((struct IORequest *)gameport_io);
  841.     gameport_io_in_progress = FALSE;
  842.     gameport_ct = GPCT_NOCONTROLLER;
  843.     gameport_io->io_Command = GPD_SETCTYPE;
  844.     gameport_io->io_Length = 1;
  845.     gameport_io->io_Data = &gameport_ct;
  846.     DoIO ((struct IORequest *)gameport_io);
  847.   }
  848.   if (gameport_is_open) {
  849.     CloseDevice ((struct IORequest *)gameport_io);
  850.     gameport_is_open = FALSE;
  851.   }
  852.   if (gameport_io != NULL) {
  853.     DeleteExtIO ((struct IORequest *)gameport_io);
  854.     gameport_io = NULL;
  855.   }
  856.   if (gameport_mp != NULL) {
  857.     DeletePort (gameport_mp);
  858.     gameport_mp = NULL;
  859.   }
  860.   if (video_blit_is_in_progress) {
  861.     Wait (SIGBREAKF_CTRL_F);
  862.     video_blit_is_in_progress = FALSE;
  863.   }
  864.   if (video_fliptask != NULL) {
  865.     Signal (video_fliptask, SIGBREAKF_CTRL_C);
  866.     Wait (SIGBREAKF_CTRL_F);
  867.     DeleteTask (video_fliptask);
  868.     video_fliptask = NULL;
  869.   }
  870.   if (video_is_using_blitter) {
  871.     if (video_sigbit1 != -1) {
  872.       Wait (1 << video_sigbit1);  // wait for last c2p8 to finish pass 3
  873.     FreeSignal (video_sigbit1);
  874.       video_sigbit1 = -1;
  875.     }
  876.     if (video_sigbit2 != -1) {
  877.       Wait (1 << video_sigbit2);  // wait for last c2p8 to completely finish
  878.     FreeSignal (video_sigbit2);
  879.       video_sigbit2 = -1;
  880.     }
  881.   }
  882.   if (video_window != NULL) {
  883.     ClearPointer (video_window);
  884.     CloseWindow (video_window);
  885.     video_window = NULL;
  886.   }
  887.   if (video_is_using_blitter) {
  888.     for (i = 0; i < 2; i++) {
  889.       if (video_sb[i] != NULL) {
  890.     FreeScreenBuffer (video_screen, video_sb[i]);
  891.     video_sb[i] = NULL;
  892.       }
  893.     }
  894.   } else {
  895.     if (video_mp) {
  896.       WaitPort (video_mp);
  897.       while (GetMsg(video_mp));
  898.       DeleteMsgPort (video_mp);
  899.       video_mp = NULL; 
  900.     }
  901.     if (video_db) {
  902.       FreeDBufInfo (video_db);
  903.       video_db = NULL;
  904.     }
  905.   }
  906. #ifdef GRAFFITI
  907.   if (video_grf_screen != NULL) {
  908.     CloseChunkyScreen (video_grf_screen);
  909.     video_grf_screen = NULL;
  910.     video_screen = NULL;
  911.   }
  912.   if (GraffitiBase != NULL) {
  913.     CloseLibrary (GraffitiBase);
  914.     GraffitiBase = NULL;
  915.   }
  916. #endif
  917.   if (video_screen != NULL) {
  918.     CloseScreen (video_screen);
  919.     video_screen = NULL;
  920.   }
  921.   for (depth = 0; depth < video_depth; depth++) {
  922.     if (video_tmp_bm.Planes[depth] != NULL) {
  923.       FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
  924.       video_tmp_bm.Planes[depth] = NULL;
  925.     }
  926.   }
  927.   if (video_chipbuff != NULL) {
  928.     FreeMem (video_chipbuff, 2 * SCREENWIDTH * SCREENHEIGHT);
  929.     video_chipbuff = NULL;
  930.   }
  931.   for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  932.     if (video_raster[i] != NULL) {
  933.       if (video_use_mmu) {
  934.         ULONG *ptr = (ULONG *)video_raster[i];
  935.         UBYTE *p2 = (UBYTE *)ptr;
  936.         mmu_mark (video_raster[i], SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  937.                   video_c_cache_mode, SysBase);
  938.         FreeVec (p2 - ptr[-1]);
  939.       } else
  940.         FreeRaster (video_raster[i], SCREENWIDTH, video_depth * SCREENHEIGHT);
  941.       video_raster[i] = NULL;
  942.     }
  943.     if (video_compare_buffer[i] != NULL) {
  944.       free (video_compare_buffer[i]);
  945.       video_compare_buffer[i] = NULL;
  946.     }
  947.   }
  948.   if (video_use_mmu && !video_is_directcgx) {
  949.     if (screens[0] != NULL)
  950.       mmu_mark (screens[0], (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  951.                 video_f_cache_mode, SysBase);
  952.   }
  953.   if (KeymapBase == NULL) {
  954.     CloseLibrary (KeymapBase);
  955.     KeymapBase = NULL;
  956.   }
  957.   if (CyberGfxBase == NULL) {
  958.     CloseLibrary (CyberGfxBase);
  959.     CyberGfxBase = NULL;
  960.   }
  961.   /* experimental c2p stuff */
  962.   if (c2p && !video_is_using_blitter) {
  963.     c2p8_deinit (c2p, SysBase);
  964.     c2p = NULL;
  965.   }
  966.   if (!timerclosed) {
  967.     if (!CheckIO((struct IORequest *)timerio)) {
  968.       AbortIO ((struct IORequest *)timerio);
  969.       WaitIO ((struct IORequest *)timerio);
  970.     }
  971.     CloseDevice ((struct IORequest *)timerio);
  972.     timerclosed = TRUE;
  973.     TimerBase = NULL;
  974.   }
  975.   if (timerio != NULL) {
  976.     DeleteExtIO ((struct IORequest *)timerio);
  977.     timerio = NULL;
  978.   }
  979.   if (timermp != NULL) {
  980.     DeletePort (timermp);
  981.     timermp = NULL;
  982.   }
  983. }
  984.  
  985. /**********************************************************************/
  986. // recalculate colourtable[][] after changing usegamma
  987. void I_RecalcPalettes (void)
  988. {
  989.   int p, i;
  990.   byte *palette;
  991.   static UBYTE gpalette[3*256];
  992.   static int lu_palette;
  993.  
  994.   lu_palette = W_GetNumForName ("PLAYPAL");
  995.   for (p = 0; p < NUMPALETTES; p++) {
  996.     palette = (byte *) W_CacheLumpNum (lu_palette, PU_STATIC)+p*768;
  997.     if (video_is_ehb_mode) {
  998.       i = 3 * 256 - 1;
  999.       do {
  1000.         gpalette[i] = gammatable[usegamma][palette[i]];
  1001.       } while (--i >= 0);
  1002.       video_colourtable[p][0] = (32 << 16) + 0;
  1003.       median_cut (gpalette, &video_colourtable[p][1], video_xlate[p]);
  1004.       video_colourtable[p][33] = 0;
  1005.     } else {
  1006. #ifdef GRAFFITI
  1007.       if (video_graffiti != 0) {
  1008.         for (i = 0; i < 256; i++)
  1009.           video_colourtable[p][i] =
  1010.                       (((UBYTE)gammatable[usegamma][palette[3*i+0]]) << 16) +
  1011.                       (((UBYTE)gammatable[usegamma][palette[3*i+1]]) << 8) +
  1012.                        ((UBYTE)gammatable[usegamma][palette[3*i+2]]);
  1013.       } else {
  1014. #endif
  1015.         i = 3 * 256 - 1;
  1016.         video_colourtable[p][i + 2] = 0;
  1017.         do {
  1018.           // Better to define c locally here instead of for the whole function:
  1019.           ULONG c = gammatable[usegamma][palette[i]];
  1020.           c += (c << 8);
  1021.           video_colourtable[p][i + 1] = (c << 16) + c;
  1022.         } while (--i >= 0);
  1023.         video_colourtable[p][0] = (256 << 16) + 0;
  1024. #ifdef GRAFFITI
  1025.       }
  1026. #endif
  1027.     }
  1028.   }
  1029. }
  1030.  
  1031. /**********************************************************************/
  1032. // Takes full 8 bit values.
  1033. void I_SetPalette (byte *palette, int palette_index)
  1034. {
  1035.   if (video_is_ehb_mode)
  1036.     if (video_is_using_blitter) {
  1037.       video_palette_changed = 2;  /* double buffering */
  1038.       video_pending_palette_index = palette_index;
  1039.     } else {
  1040.       video_palette_changed = 3;  /* triple buffering */
  1041.       video_palette_index = palette_index;
  1042.     }
  1043.   else {
  1044.     video_palette_changed = 1;
  1045.     video_palette_index = palette_index;
  1046.   }
  1047. }
  1048.  
  1049. /**********************************************************************/
  1050. // Called by anything that renders to screens[0] (except 3D view)
  1051. void I_MarkRect (int left, int top, int width, int height)
  1052. {
  1053.   M_AddToBox (dirtybox, left, top);
  1054.   M_AddToBox (dirtybox, left + width - 1, top + height - 1);
  1055. }
  1056.  
  1057. /**********************************************************************/
  1058. void I_StartUpdate (void)
  1059. {
  1060.   UBYTE *base_address;
  1061.  
  1062.   if (video_is_directcgx) {
  1063.     if (video_palette_changed != 0) {
  1064.       LoadRGB32 (&video_screen->ViewPort,
  1065.                  video_colourtable[video_palette_index]);
  1066.       video_palette_changed = 0;
  1067.     }
  1068.     if (!video_bitmap_is_locked) {
  1069.       start_timer ();
  1070.       video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  1071.                                             LBMI_BASEADDRESS, &base_address,
  1072.                                             TAG_DONE);
  1073.       lock_time += end_timer ();
  1074.       video_bitmap_is_locked = TRUE;
  1075.       video_which = 1 - video_which;
  1076.       if (video_which != 0)
  1077.         screens[0] = base_address + (SCREENWIDTH * video_oscan_height);
  1078.       else
  1079.         screens[0] = base_address;
  1080.       R_InitBuffer (scaledviewwidth, viewheight); /* recalc ylookup2[] */
  1081.     }
  1082.   }
  1083. }
  1084.  
  1085. /**********************************************************************/
  1086. void I_UpdateNoBlit (void)
  1087. {
  1088. }
  1089.  
  1090. /**********************************************************************/
  1091. void I_FinishUpdate (void)
  1092. /* This needs optimising to copy just the parts that changed,
  1093.    especially if the user has shrunk the playscreen. */
  1094. {
  1095.   int top, left, width, height;
  1096.  
  1097.   total_frames++;
  1098.  
  1099. #ifdef GRAFFITI
  1100.   if (video_graffiti != 0) {
  1101.     start_timer();
  1102.     CopyChunkyScreen (video_grf_screen, screens[0]);
  1103.     SetChunkyPalette (video_grf_screen,
  1104.                       (long *)video_colourtable[video_palette_index]);
  1105.     video_palette_changed = 0;
  1106.     ccs_time += end_timer();
  1107.     return;
  1108.   }
  1109. #endif
  1110.  
  1111.   if (video_is_directcgx) {
  1112.     if (video_bitmap_is_locked) {
  1113.       UnLockBitMap (video_bitmap_handle);
  1114.       video_bitmap_is_locked = FALSE;
  1115.  
  1116.       video_screen->ViewPort.RasInfo->RyOffset = video_which != 0 ?
  1117.                                                          video_oscan_height : 0;
  1118.       ScrollVPort (&video_screen->ViewPort);
  1119.  
  1120.       /* copy dirtybox into other buffer, hopefully using gfx-card blitter!? */
  1121.       if (dirtybox[BOXRIGHT] >= dirtybox[BOXLEFT] &&
  1122.           dirtybox[BOXTOP] >= dirtybox[BOXBOTTOM])
  1123.         if (video_which != 0)
  1124.           ClipBlit (video_window->RPort,
  1125.                     dirtybox[BOXLEFT], video_oscan_height + dirtybox[BOXBOTTOM],
  1126.                     video_window->RPort,
  1127.                     dirtybox[BOXLEFT], dirtybox[BOXBOTTOM],
  1128.                     dirtybox[BOXRIGHT] - dirtybox[BOXLEFT] + 1,
  1129.                     dirtybox[BOXTOP] - dirtybox[BOXBOTTOM] + 1,
  1130.                     0xc0);
  1131.         else
  1132.           ClipBlit (video_window->RPort,
  1133.                     dirtybox[BOXLEFT], dirtybox[BOXBOTTOM],
  1134.                     video_window->RPort,
  1135.                     dirtybox[BOXLEFT], video_oscan_height + dirtybox[BOXBOTTOM],
  1136.                     dirtybox[BOXRIGHT] - dirtybox[BOXLEFT] + 1,
  1137.                     dirtybox[BOXTOP] - dirtybox[BOXBOTTOM] + 1,
  1138.                     0xc0);
  1139.       M_ClearBox (dirtybox);
  1140.  
  1141.     } else
  1142.       I_Error ("I_FinishUpdate() called without calling I_StartUpdate() first");
  1143.  
  1144.     if (video_doing_fps)
  1145.       video_do_fps (video_window->RPort,
  1146.                     video_which != 0 ? video_oscan_height : 0);
  1147.     return;
  1148.   }
  1149.  
  1150.   /* update only the viewwindow and dirtybox when gamestate == GS_LEVEL */
  1151.   if (gamestate == GS_LEVEL) {
  1152.     if (dirtybox[BOXLEFT] < viewwindowx)
  1153.       left = dirtybox[BOXLEFT];
  1154.     else
  1155.       left = viewwindowx;
  1156.     if (dirtybox[BOXRIGHT] + 1 > viewwindowx + scaledviewwidth)
  1157.       width = dirtybox[BOXRIGHT] + 1 - left;
  1158.     else
  1159.       width = viewwindowx + scaledviewwidth - left;
  1160.     if (dirtybox[BOXBOTTOM] < viewwindowy) /* BOXBOTTOM is really the top! */
  1161.       top = dirtybox[BOXBOTTOM];
  1162.     else
  1163.       top = viewwindowy;
  1164.     if (dirtybox[BOXTOP] + 1 > viewwindowy + viewheight)
  1165.       height = dirtybox[BOXTOP] + 1 - top;
  1166.     else
  1167.       height = viewwindowy + viewheight - top;
  1168.     M_ClearBox (dirtybox);
  1169. #ifdef RANGECHECK
  1170.     if (left < 0 || left + width > SCREENWIDTH ||
  1171.         top < 0 || top + height > SCREENHEIGHT)
  1172.       I_Error ("I_FinishUpdate: Box out of range: %d %d %d %d",
  1173.                left, top, width, height);
  1174. #endif
  1175.   } else {
  1176.     left = 0;
  1177.     top = 0;
  1178.     width = SCREENWIDTH;
  1179.     height = SCREENHEIGHT;
  1180.   }
  1181.  
  1182.   if (video_is_native_mode) {
  1183.     if (video_is_using_blitter) {
  1184.       start_timer();
  1185.       Wait (1 << video_sigbit1); /* wait for prev c2p() to finish pass 3 */
  1186.       blit_time += end_timer();
  1187.       if (video_blit_is_in_progress) {
  1188.     start_timer();
  1189.     Wait (SIGBREAKF_CTRL_F); /* wait for prev ChangeScreenBuffer() safe */
  1190.     safe_time += end_timer();
  1191.     video_blit_is_in_progress = FALSE;
  1192.       }
  1193.       video_which = 1 - video_which;  /* render to the hidden bitmap */
  1194.       start_timer();
  1195.       if (video_is_ehb_mode) {
  1196.         video_palette_index = video_pending_palette_index;
  1197.         c2p_6_020 (&screens[0][SCREENWIDTH * top],
  1198.                    video_bitmap[video_which].Planes,
  1199.                    1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  1200.                    SCREENWIDTH * height, (SCREENWIDTH >> 3) * top,
  1201.                    video_xlate[video_palette_index], video_fliptask,
  1202.                    video_chipbuff);
  1203.       } else {
  1204.         if (cpu_type < 68030)
  1205.           c2p_8_020 (&screens[0][SCREENWIDTH * top],
  1206.                      video_bitmap[video_which].Planes,
  1207.                      1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  1208.                      SCREENWIDTH * height, (SCREENWIDTH >> 3) * top,
  1209.                      video_fliptask, video_chipbuff);
  1210.         else
  1211.           c2p1x1_cpu3blit1_queue (screens[0], video_raster[video_which]);
  1212.       }
  1213.       c2p_time += end_timer();
  1214.       video_blit_is_in_progress = TRUE;
  1215.     } else {
  1216.       start_timer();
  1217.       if (video_is_ehb_mode) {
  1218.         c2p_6_040 (screens[0], video_raster[video_which],
  1219.                    video_compare_buffer[video_which],
  1220.                    video_xlate[video_palette_index],
  1221.                    (SCREENWIDTH * SCREENHEIGHT) >> 3,
  1222.                    video_palette_changed);
  1223.         if (video_palette_changed > 0) {
  1224.           if (video_palette_changed == 3)
  1225.             LoadRGB32 (&video_screen->ViewPort,
  1226.                        video_colourtable[video_palette_index]);
  1227.           video_palette_changed--;
  1228.         }
  1229.       } else {
  1230.         if (c2p && scaledviewwidth >= SCREENWIDTH-64)
  1231.            c2p (screens[0], video_raster[video_which],
  1232.                 screens[0] + SCREENWIDTH * SCREENHEIGHT);
  1233.         else
  1234.           c2p_8_040 (screens[0], video_raster[video_which],
  1235.                      video_compare_buffer[video_which],
  1236.                      (SCREENWIDTH * SCREENHEIGHT) >> 3);
  1237.         if (video_palette_changed != 0) {
  1238.           LoadRGB32 (&video_screen->ViewPort,
  1239.                      video_colourtable[video_palette_index]);
  1240.           video_palette_changed = 0;
  1241.         }
  1242.       }
  1243.       c2p_time += end_timer();
  1244.       if (video_doing_fps)
  1245.         video_do_fps (&video_rastport[video_which], 0);
  1246.       WaitPort (video_mp);
  1247.       while (GetMsg (video_mp))
  1248.     /* do nothing */ ;
  1249.       ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[video_which],
  1250.                       video_db);
  1251.       if (++video_which == 3)
  1252.         video_which = 0;
  1253.     }
  1254.   } else {  /* non-native ScreenMode */
  1255.     if (video_palette_changed != 0) {
  1256.       LoadRGB32 (&video_screen->ViewPort,
  1257.                  video_colourtable[video_palette_index]);
  1258.       video_palette_changed = 0;
  1259.     }
  1260.     start_timer();
  1261.     if (GfxBase->LibNode.lib_Version >= 40)
  1262.       WriteChunkyPixels (video_window->RPort, left, top, left+width-1,
  1263.                          top+height-1, &screens[0][SCREENWIDTH * top + left],
  1264.                          SCREENWIDTH);
  1265.     else
  1266.       WritePixelArray8 (video_window->RPort, 0, top, SCREENWIDTH-1,
  1267.                         top+height-1, &screens[0][SCREENWIDTH * top],
  1268.                         &video_temprp);
  1269.     wpa8_time += end_timer();
  1270.     if (video_doing_fps)
  1271.       video_do_fps (video_window->RPort, 0);
  1272.   }
  1273. }
  1274.  
  1275. /**********************************************************************/
  1276. // Wait for vertical retrace or pause a bit.  Use when quit game.
  1277. void I_WaitVBL(int count)
  1278. {
  1279.   for ( ; count > 0; count--)
  1280.     WaitTOF();
  1281. }
  1282.  
  1283. /**********************************************************************/
  1284. void I_ReadScreen (byte* scr)
  1285. {
  1286.   UBYTE *base_address;
  1287.  
  1288.   if (video_is_directcgx)
  1289.     if (video_bitmap_is_locked) {
  1290.       UnLockBitMap (video_bitmap_handle);
  1291.       ReadPixelArray8 (video_window->RPort, 0,
  1292.                        video_which != 0 ? video_oscan_height : 0,
  1293.                        SCREENWIDTH-1, SCREENHEIGHT-1, scr, &video_temprp);
  1294.       video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  1295.                                             LBMI_BASEADDRESS, &base_address,
  1296.                                             TAG_DONE);
  1297.       if (video_which != 0)
  1298.         screens[0] = base_address + (SCREENWIDTH * video_oscan_height);
  1299.       else
  1300.         screens[0] = base_address;
  1301.       R_InitBuffer (scaledviewwidth, viewheight); /* recalc ylookup2[] */
  1302.     } else
  1303.       ReadPixelArray8 (video_window->RPort, 0,
  1304.                        video_which != 0 ? video_oscan_height : 0,
  1305.                        SCREENWIDTH-1, SCREENHEIGHT-1, scr, &video_temprp);
  1306.   else
  1307.     memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
  1308. }
  1309.  
  1310. /**********************************************************************/
  1311. void I_BeginRead (void)
  1312. {
  1313. }
  1314.  
  1315. /**********************************************************************/
  1316. void I_EndRead (void)
  1317. {
  1318. }
  1319.  
  1320. /**********************************************************************/
  1321.  
  1322. int xlate_key (UWORD rawkey, UWORD qualifier, APTR *eventptr)
  1323. {
  1324.   char buffer[4], c;
  1325.   struct InputEvent ie;
  1326.   static int xlate[0x68] = {
  1327.     '`', '1', '2', '3', '4', '5', '6', '7',
  1328.     '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
  1329.     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  1330.     'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
  1331.     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
  1332.     'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
  1333.     KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
  1334.     ',', '.', '/', 0, '.', '7', '8', '9',
  1335.     ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_F11,
  1336.     0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
  1337.     KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
  1338.     KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
  1339.     KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
  1340.   };
  1341.  
  1342.   if (video_is_rawkey)
  1343.     if (rawkey < 0x68)
  1344.       return xlate[rawkey];
  1345.     else
  1346.       return 0;
  1347.   else
  1348.     if (rawkey > 0x00 && rawkey < 0x0a) // '1'..'9', no SHIFT French keyboards
  1349.       return '0' + rawkey;
  1350.     else if (rawkey == 0x0a)            // '0'
  1351.       return '0';
  1352.     else if (rawkey < 0x40) {
  1353.       ie.ie_Class = IECLASS_RAWKEY;
  1354.       ie.ie_Code = rawkey;
  1355.       ie.ie_Qualifier = qualifier;
  1356.       ie.ie_EventAddress = *eventptr;
  1357.       if (MapRawKey (&ie, buffer, sizeof(buffer), NULL) > 0) {
  1358.         c = buffer[0];
  1359.         if (c >= '0' && c <= '9')       /* numeric pad */
  1360.           switch (c) {
  1361.           case '0':
  1362.             return ' ';
  1363.           case '1':
  1364.             return ',';
  1365.           case '2':
  1366.             return KEY_RCTRL;
  1367.           case '3':
  1368.             return '.';
  1369.           case '4':
  1370.             return KEY_LEFTARROW;
  1371.           case '5':
  1372.             return KEY_DOWNARROW;
  1373.           case '6':
  1374.             return KEY_RIGHTARROW;
  1375.           case '7':
  1376.             return ',';
  1377.           case '8':
  1378.             return KEY_UPARROW;
  1379.           case '9':
  1380.             return '.';
  1381.           }
  1382.         else if (c >= 'A' && c <= 'Z')
  1383.           return c - 'A' + 'a';
  1384.         else if (c == '<')
  1385.           return ',';
  1386.         else if (c == '>')
  1387.           return '.';
  1388.         else if (c == '-')
  1389.           return KEY_MINUS;
  1390.         else if (c == '=')
  1391.           return KEY_EQUALS;
  1392.         else if (c == '[')
  1393.           return KEY_F11;
  1394.         else if (c == ']')
  1395.           return KEY_F12;
  1396.         else if (c == '\r')
  1397.           return KEY_ENTER;
  1398.         else if (c == '\n')
  1399.           return KEY_ENTER;
  1400.         else
  1401.           return c;
  1402.       } else
  1403.         return 0;
  1404.     } else if (rawkey < 0x68)
  1405.       return xlate[rawkey];
  1406.     else
  1407.       return 0;
  1408. }
  1409.  
  1410. /**********************************************************************/
  1411. void amiga_getevents (void)
  1412. {
  1413.   event_t event;
  1414.   ULONG class;
  1415.   UWORD code;
  1416.   WORD mousex, mousey;
  1417.   struct IntuiMessage *msg;
  1418.   static ULONG previous = 0;
  1419.   static event_t joyevent = {0}, mouseevent = {0};
  1420.   ULONG currSega;
  1421.   int doomkey;
  1422.  
  1423.   if (video_window != NULL) {
  1424.     while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
  1425.       class = msg->Class;
  1426.       code = msg->Code;
  1427.       mousex = msg->MouseX;
  1428.       mousey = msg->MouseY;
  1429.       if (class == IDCMP_RAWKEY) {
  1430.         if ((code & 0x80) != 0) {
  1431.           code &= ~0x80;
  1432.       event.type = ev_keyup;
  1433.         } else {
  1434.           event.type = ev_keydown;
  1435.         }
  1436.         if (code < 0x68)
  1437.           doomkey = xlate_key (code, msg->Qualifier, msg->IAddress);
  1438.       }
  1439.       ReplyMsg ((struct Message *)msg);  /* reply after xlating key */
  1440.       if (class == IDCMP_RAWKEY) {
  1441.         if (code < 0x68 && doomkey != 0) {
  1442.           event.data1 = doomkey;
  1443.           D_PostEvent (&event);
  1444.           /* printf ("key %02x -> %02x\n", code, doomkey); */
  1445.         }
  1446.       } else if (class == IDCMP_MOUSEMOVE) {
  1447.         mouseevent.type = ev_mouse;
  1448.         mouseevent.data2 = (mousex << 3);
  1449.         mouseevent.data3 = -(mousey << 5);
  1450.         D_PostEvent (&mouseevent);
  1451.       } else if (class == IDCMP_MOUSEBUTTONS) {
  1452.         mouseevent.type = ev_mouse;
  1453.         switch (code) {
  1454.           case SELECTDOWN:
  1455.             mouseevent.data1 |= 1;
  1456.             break;
  1457.           case SELECTUP:
  1458.             mouseevent.data1 &= ~1;
  1459.             break;
  1460.           case MENUDOWN:
  1461.             mouseevent.data1 |= 2;
  1462.             break;
  1463.           case MENUUP:
  1464.             mouseevent.data1 &= ~2;
  1465.             break;
  1466.           case MIDDLEDOWN:
  1467.             mouseevent.data1 |= 4;
  1468.             break;
  1469.           case MIDDLEUP:
  1470.             mouseevent.data1 &= ~4;
  1471.             break;
  1472.           default:
  1473.             break;
  1474.         }
  1475.         D_PostEvent (&mouseevent);
  1476.       }
  1477.     }
  1478.   }
  1479.  
  1480.   if (gameport_is_open && gameport_io_in_progress) {
  1481.     while (GetMsg (gameport_mp) != NULL) {
  1482.       switch (gameport_ie.ie_Code) {
  1483.         case IECODE_LBUTTON:
  1484.           joyevent.data1 |= 1;
  1485.           break;
  1486.         case IECODE_LBUTTON | IECODE_UP_PREFIX:
  1487.           joyevent.data1 &= ~1;
  1488.           break;
  1489.         case IECODE_RBUTTON:
  1490.           joyevent.data1 |= 2;
  1491.           break;
  1492.         case IECODE_RBUTTON | IECODE_UP_PREFIX:
  1493.           joyevent.data1 &= ~2;
  1494.           break;
  1495.         case IECODE_MBUTTON:
  1496.           joyevent.data1 |= 4;
  1497.           break;
  1498.         case IECODE_MBUTTON | IECODE_UP_PREFIX:
  1499.           joyevent.data1 &= ~4;
  1500.           break;
  1501.         case IECODE_NOBUTTON:
  1502.           joyevent.data2 = gameport_ie.ie_X;
  1503.           joyevent.data3 = gameport_ie.ie_Y;
  1504.           break;
  1505.         default:
  1506.           break;
  1507.       }
  1508.       joyevent.type = ev_joystick;
  1509.       D_PostEvent (&joyevent);
  1510.       gameport_io->io_Command = GPD_READEVENT;
  1511.       gameport_io->io_Length = sizeof (struct InputEvent);
  1512.       gameport_io->io_Data = &gameport_ie;
  1513.       SendIO ((struct IORequest *)gameport_io);
  1514.     }
  1515.   }
  1516.  
  1517.   /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
  1518.  
  1519.   if (LowLevelBase != NULL) {
  1520.     event_t joyevent;
  1521.     ULONG joypos = ReadJoyPort (1);
  1522.  
  1523.     if (previous == joypos)
  1524.       return;
  1525.  
  1526.     joyevent.type = ev_joystick;
  1527.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1528.  
  1529.     if (joypos & JPF_BUTTON_RED)
  1530.       joyevent.data1 |= 1;
  1531.     else
  1532.       joyevent.data1 &= ~1;
  1533.  
  1534.     if (joypos & JP_DIRECTION_MASK) {
  1535.       if (joypos & JPF_JOY_LEFT) {
  1536.         joyevent.data2 = -1;
  1537.       } else if (joypos & JPF_JOY_RIGHT) {
  1538.         joyevent.data2 = 1;
  1539.       }
  1540.       if (joypos & JPF_JOY_UP) {
  1541.         joyevent.data3 = -1;
  1542.       } else if (joypos & JPF_JOY_DOWN) {
  1543.         joyevent.data3 = 1;
  1544.       }
  1545.     }
  1546.  
  1547.     if (joypos & JP_TYPE_GAMECTLR) {
  1548.       event_t event;
  1549.  
  1550.       // Play/Pause = ESC (Menu)
  1551.       if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
  1552.         event.type = ev_keydown;
  1553.         event.data1 = KEY_ESCAPE;
  1554.         D_PostEvent (&event);
  1555.       } else if (previous & JPF_BUTTON_PLAY) {
  1556.         event.type = ev_keyup;
  1557.         event.data1 = KEY_ESCAPE;
  1558.         D_PostEvent (&event);
  1559.       }
  1560.  
  1561.       // YELLOW = SHIFT (button 2) (Run)
  1562.       if (joypos & JPF_BUTTON_YELLOW)
  1563.         joyevent.data1 |= 4;
  1564.       else
  1565.         joyevent.data1 &= ~4;
  1566.  
  1567.       // BLUE = SPACE (button 3) (Open/Operate)
  1568.  
  1569.       if (joypos & JPF_BUTTON_BLUE)
  1570.         joyevent.data1 |= 8;
  1571.       else
  1572.         joyevent.data1 &= ~8;
  1573.  
  1574.       // GREEN = RETURN (show msg)
  1575.  
  1576.       if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
  1577.         event.type = ev_keydown;
  1578.         event.data1 = 13;
  1579.         D_PostEvent (&event);
  1580.       } else if (previous & JPF_BUTTON_GREEN) {
  1581.         event.type = ev_keyup;
  1582.         event.data1 = 13;
  1583.         D_PostEvent (&event);
  1584.       }
  1585.  
  1586.       // FORWARD & REVERSE - ALT (Button1) Strafe left/right
  1587.  
  1588.       if (joypos & JPF_BUTTON_FORWARD) {
  1589.         joyevent.data1 |= 2;
  1590.         joyevent.data2 = 1;
  1591.       } else if (joypos & JPF_BUTTON_REVERSE) {
  1592.         joyevent.data1 |=2;
  1593.         joyevent.data2=-1;
  1594.       } else
  1595.         joyevent.data1 &= ~2;
  1596.     }
  1597.  
  1598.     D_PostEvent (&joyevent);
  1599.  
  1600.     previous = joypos;
  1601.   }
  1602.  
  1603.   /* SEGA joypad handler code by Joe Fenton, loosely based on CD32 handling */
  1604.  
  1605.   if (sega3_selected || sega6_selected) {
  1606.     event_t joyevent, event;
  1607.  
  1608.     if (sega3_selected) {
  1609.       currSega = Sega3 ();
  1610.     } else {
  1611.       currSega = Sega6 ();
  1612.     }
  1613.  
  1614.     if (prevSega == currSega)
  1615.       return;
  1616.  
  1617.     joyevent.type = ev_joystick;
  1618.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1619.  
  1620.     // B = fire
  1621.     if (currSega & 0x10)
  1622.       joyevent.data1 |= 1;
  1623.     else
  1624.       joyevent.data1 &= ~1;
  1625.  
  1626.     // directionals
  1627.     if (currSega & 0xF) {
  1628.       if (currSega & 4) {
  1629.         joyevent.data2 = -1;
  1630.       } else if (currSega & 8) {
  1631.         joyevent.data2 = 1;
  1632.       }
  1633.       if (currSega & 1) {
  1634.         joyevent.data3 = -1;
  1635.       } else if (currSega & 2) {
  1636.         joyevent.data3 = 1;
  1637.       }
  1638.     }
  1639.  
  1640.     // Mode = ESC (Menu)
  1641.     if (currSega & 0x80000 && !(prevSega & 0x80000)) {
  1642.       event.type = ev_keydown;
  1643.       event.data1 = KEY_ESCAPE;
  1644.       D_PostEvent (&event);
  1645.     } else if (prevSega & 0x80000) {
  1646.       event.type = ev_keyup;
  1647.       event.data1 = KEY_ESCAPE;
  1648.       D_PostEvent (&event);
  1649.     }
  1650.  
  1651.     // Y = SHIFT (Run)
  1652.     if (currSega & 0x20000)
  1653.       joyevent.data1 |= 4;
  1654.     else
  1655.       joyevent.data1 &= ~4;
  1656.  
  1657.     // Start = SPACE (Open/Operate)
  1658.     if (currSega & 0x2000)
  1659.       joyevent.data1 |= 8;
  1660.     else
  1661.       joyevent.data1 &= ~8;
  1662.  
  1663.     // A & C - ALT (Button1) Strafe left/right
  1664.     if (currSega & 0x20) {
  1665.       joyevent.data1 |= 2;
  1666.       joyevent.data2 = 1;
  1667.     } else if (currSega & 0x1000) {
  1668.       joyevent.data1 |=2;
  1669.       joyevent.data2=-1;
  1670.     } else
  1671.       joyevent.data1 &= ~2;
  1672.  
  1673.     // X = RETURN (show msg)
  1674.     if (currSega & 0x40000 && !(prevSega&0x40000)) {
  1675.       event.type = ev_keydown;
  1676.       event.data1 = 13;
  1677.       D_PostEvent (&event);
  1678.     } else if (prevSega & 0x40000) {
  1679.       event.type = ev_keyup;
  1680.       event.data1 = 13;
  1681.       D_PostEvent (&event);
  1682.     }
  1683.  
  1684.     // Z = TAB (show map)
  1685.     if (currSega & 0x10000 && !(prevSega&0x10000)) {
  1686.       event.type = ev_keydown;
  1687.       event.data1 = 9;
  1688.       D_PostEvent (&event);
  1689.     } else if (prevSega & 0x10000) {
  1690.       event.type = ev_keyup;
  1691.       event.data1 = 9;
  1692.       D_PostEvent (&event);
  1693.     }
  1694.  
  1695.     D_PostEvent (&joyevent);
  1696.  
  1697.     prevSega = currSega;
  1698.   }
  1699.  
  1700. }
  1701.  
  1702. /**********************************************************************/
  1703. static void calc_time (ULONG time, char *msg)
  1704. {
  1705.   printf ("Total %s = %u us  (%u us/frame)\n", msg,
  1706.           (ULONG)(1000000.0 * ((double)time) / ((double)eclocks_per_second)),
  1707.           (ULONG)(1000000.0 * ((double)time) / ((double)eclocks_per_second) /
  1708.                   ((double)total_frames)));
  1709. }
  1710.  
  1711. /**********************************************************************/
  1712. void _STDvideo_cleanup (void)
  1713. {
  1714.   I_ShutdownGraphics ();
  1715.   if (video_smr != NULL) {
  1716.     FreeAslRequest (video_smr);
  1717.     video_smr = NULL;
  1718.   }
  1719.   /* printf ("EClocks per second = %d\n", eclocks_per_second); */
  1720.   if (total_frames > 0) {
  1721.     printf ("Total number of frames = %u\n", total_frames);
  1722.     calc_time (blit_time, "blit wait time        ");
  1723.     calc_time (safe_time, "safe wait time        ");
  1724.     calc_time (c2p_time,  "Chunky2Planar time    ");
  1725.     calc_time (ccs_time,  "CopyChunkyScreen time ");
  1726.     calc_time (wpa8_time, "WritePixelArray8 time ");
  1727.     calc_time (lock_time, "LockBitMap time       ");
  1728.   }
  1729. }
  1730.  
  1731. /**********************************************************************/
  1732.